package com.common.android.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
 * MD5相关工具类
 * <br>Created 2014-8-22 下午4:07:24
 * @version  
 * @author   huangyx		
 * @see 	 
 * Copyright(c) 2009-2014, TQ Digital Entertainment, All Rights Reserved
 *
 */
public class MD5ArithmeticUtils {
    
	private static MessageDigest messageDigestMD5 = null;
	
	/**
	 * Creates a new instance of MD5ArithmeticUtils.
	 * <br>Created 2014-8-27 上午9:56:48
	 */
	public MD5ArithmeticUtils() {
		try {
			messageDigestMD5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("No MD5 algorithm.");
		}
	}
	
	/**
	 * 获取MD5
	 * <br>Created 2014-8-22 下午4:08:07
	 * @param url 源url
	 * @return 返回MD5
	 * @author       huangyx
	 */
	public static synchronized String getMd5(String url) {
		if (url == null) {
		    url = "";
		}
		if(messageDigestMD5 == null){
			try {
				messageDigestMD5 = MessageDigest.getInstance("MD5");
			} catch (NoSuchAlgorithmException e) {
				throw new RuntimeException("No MD5 algorithm.");
			}
		}
		messageDigestMD5.update(url.getBytes());
		return getHashString(messageDigestMD5);
	}

	/**
	 * 获取Hash字符串
	 * <br>Created 2014-8-22 下午4:09:12
	 * @param digest MessageDigest对象
	 * @return Hash字符串
	 * @author       huangyx
	 */
	private static String getHashString(MessageDigest digest) {
		StringBuilder builder = new StringBuilder();
		for (byte b : digest.digest()) {
			builder.append(Integer.toHexString((b >> 4) & 0xf));
			builder.append(Integer.toHexString(b & 0xf));
		}
		return builder.toString();
	}
	 
	/**
	 * 对文件计算md5
	 * <br>Created 2014-8-22 下午4:15:16
	 * @param path 文件路径
	 * @return 文件的md5
	 * @author       huangyx
	 */
    public static String md5Sum(String path) {
    	String result = "";
    	try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			InputStream is = new FileInputStream(path);
			DigestInputStream dis = new DigestInputStream(is, md);
			while (dis.read() != -1) {
			    
            }
			dis.close();
			result = new BigInteger(1, md.digest()).toString(16);
			// Android自带MD5库有问题，首位为0会被截取掉
			if(result.length() == 31){
				return "0" + result;
			}
			return result;
			
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (FileNotFoundException e2) {
			e2.printStackTrace();
		} catch (IOException e3) {
			e3.printStackTrace();
		}
		
		return result;
	}
    
    /**
     * 对字节数组计算md5
     * <br>Created 2014-8-22 下午4:16:13
     * @param buffer 字节数组
     * @return 字节数组的md5
     * @author       huangyx
     */
    public static String getMD5OfBytes(byte[] buffer) {
		String result = "";

		MessageDigest complete;
		try {
			complete = MessageDigest.getInstance("MD5");
			byte[] b = complete.digest(buffer);
			for (int i = 0; i < b.length; i++) {
				result += Integer.toString((b[i] & 0xff) + 0x100, 16)
						.substring(1);
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		return result;
	}   
       
    /**
     * 计算文件的MD5
     * <br>Created 2014-8-22 下午4:29:54
     * @param file 文件对象  
     * @return 文件的MD5
     * @throws IOException 
     * @author       huangyx
     */
    public static synchronized  String getFileEncryptString(File file) throws IOException { 
    	if (messageDigestMD5 == null) {
    		try {
    			messageDigestMD5 = MessageDigest.getInstance("MD5");
    		} catch (NoSuchAlgorithmException e) {
    			throw new RuntimeException("No MD5 algorithm.");
    		}
    	}
        FileInputStream in = new FileInputStream(file);   
        FileChannel ch = in.getChannel();   
        MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
        in.close();
      	messageDigestMD5.update(byteBuffer);
   	 	return getHashString(messageDigestMD5);   
    }   
}
